package httpserver

import (
	"context"
	"gitee.com/scottq/go-framework/src/utils"
	"github.com/gin-gonic/gin"
	"github.com/julienschmidt/httprouter"
	"net/http"
)

type Router struct {
	Path         string
	Method       string
	RouteHandler HttpRouteFunc
	Middleware   []Middleware

	HttpHandler http.Handler
}

func (r *Router) hash() string {
	return r.Method + "_" + r.Path
}

func (r *Router) invokeRegister(router *httprouter.Router, c *ServerConfig) {
	handler := r.handler(c)
	if handler != nil {
		method := r.Method
		router.Handle(method, r.Path, handler)
	}
}

func (r *Router) handlerGin(c *ServerConfig) gin.HandlerFunc {
	genCtx := func(writer http.ResponseWriter, request *http.Request, params gin.Params) *Ctx {
		ctx := NewCtx(writer, request)
		var rParams httprouter.Params
		for _, v := range params {
			rParams = append(rParams, httprouter.Param{v.Key, v.Value})
		}
		ctx._setRouterParams(rParams)
		if c.requestId {
			ctx.httpContext = context.WithValue(ctx.httpContext, c.requestIdField, utils.NewRequestId())
		}
		return ctx
	}

	if r.HttpHandler != nil {
		handler := handlerMiddleware(func(ctx *Ctx) {
			r.HttpHandler.ServeHTTP(ctx.Writer(), ctx.Request())
		}, r.Middleware)
		return func(c *gin.Context) {
			ctx := genCtx(c.Writer, c.Request, c.Params)
			handler(ctx)
		}
	}

	if r.RouteHandler != nil {
		handler := handlerMiddleware(r.RouteHandler, r.Middleware)
		return func(c *gin.Context) {
			ctx := genCtx(c.Writer, c.Request, c.Params)
			handler(ctx)
		}
	}

	return func(c *gin.Context) {

	}
}

func (r *Router) handler(c *ServerConfig) func(http.ResponseWriter, *http.Request, httprouter.Params) {
	genCtx := func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) *Ctx {
		ctx := NewCtx(writer, request)
		ctx._setRouterParams(params)
		if c.requestId {
			ctx.httpContext = context.WithValue(ctx.httpContext, c.requestIdField, utils.NewRequestId())
		}
		return ctx
	}

	if r.HttpHandler != nil {
		handler := handlerMiddleware(func(ctx *Ctx) {
			r.HttpHandler.ServeHTTP(ctx.Writer(), ctx.Request())
		}, r.Middleware)
		return func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
			ctx := genCtx(writer, request, params)
			handler(ctx)
		}
	}

	if r.RouteHandler != nil {
		handler := handlerMiddleware(r.RouteHandler, r.Middleware)
		return func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
			ctx := genCtx(writer, request, params)
			handler(ctx)
		}
	}

	return nil
}

type HttpRouteFunc = func(ctx *Ctx)
